using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using FilteredStatistics.View;
using ZoneFiveSoftware.Common.Data.Fitness;
using FilteredStatistics.Common;
using FilteredStatistics.Common.Controller;

namespace FilteredStatistics.Data
{
    class PostProcessFilterCriteria : FilterCriteriaFacade
    {
        public PostProcessFilterCriteria(Stream stream, DataVersion version)
        {
            Deserialize(stream, version);
        }

        public PostProcessFilterCriteria(IList<IPostProcessFilter> filters)
        {
            foreach (IPostProcessFilter filter in filters)
            {
                m_Filters.Add(filter.Clone());
            }

            BuildNamedZones();
        }

#region FilterCriteriaFacade members

        public override Guid ReferenceId
        {
            get { return GUIDs.PostProcessCriteriaGuid; }
        }

        public override String DisplayName
        {
            get { return PluginView.GetLocalizedString("PostProcessText"); }
        }

        public override List<object> NamedZones
        {
            get { return m_NamedZones; }
        }

        public override IActivity Activity
        {
            set { }
        }

        public override bool IsTemplateOnly
        {
            get { return false; }
        }

        public override bool IsMainViewOnly
        {
            get { return false; }
        }

        public override bool IsSerializable
        {
            get { return true; }
        }

        public override void SerializeCriteria(Stream stream)
        {
            Serialize(stream);
        }

        public override UInt16 DataVersion
        {
            get { return Constants.CurrentVersion.VersionNumber; }
        }

        public override object DeserializeCriteria(Stream stream, UInt16 version)
        {
            DataVersion dataVersion = new DataVersion(version);

            try
            {
                Deserialize(stream, dataVersion);
            }
            catch
            {
                return null;
            }

            return this;
        }

#endregion

#region IPluginSerializable members

        public override void Serialize(Stream stream)
        {
            SerializableInt32Range filterCount = new SerializableInt32Range(m_Filters.Count);

            base.Serialize(stream);

            filterCount.Serialize(stream);

            foreach (IPostProcessFilter filter in m_Filters)
            {
                filter.Serialize(stream);
            }
        }

#endregion

#region Deserialization methods

        public void Deserialize_V2(Stream stream, DataVersion version)
        {
            SerializableInt32Range filterCount = new SerializableInt32Range(0);

            filterCount.Deserialize(stream, version);
            m_Filters = new List<IPostProcessFilter>(filterCount);

            for (int i = 0; i < filterCount; ++i)
            {
                SerializableInt32Range typeData = new SerializableInt32Range(0);
                IPostProcessFilter.PostProcessType type;
                IPostProcessFilter filter = null;

                typeData.Deserialize(stream, version);
                type = (IPostProcessFilter.PostProcessType)(int)typeData;

                switch (type)
                {
                    case IPostProcessFilter.PostProcessType.MergeNearDistances:
                        {
                            filter = new MergeNearDistancesPostProcessFilter(stream, version);
                            break;
                        }
                    case IPostProcessFilter.PostProcessType.MergeNearTimes:
                        {
                            filter = new MergeNearTimesPostProcessFilter(stream, version);
                            break;
                        }
                    case IPostProcessFilter.PostProcessType.RemoveSmallDistances:
                        {
                            filter = new RemoveSmallDistancesPostProcessFilter(stream, version);
                            break;
                        }
                    case IPostProcessFilter.PostProcessType.RemoveSmallTimes:
                        {
                            filter = new RemoveSmallTimesPostProcessFilter(stream, version);
                            break;
                        }
                    case IPostProcessFilter.PostProcessType.RemoveAscentRange:
                        {
                            filter = new RemoveAscentRangeSectionsPostProcessFilter(stream, version);
                            break;
                        }
                    case IPostProcessFilter.PostProcessType.RemoveDescentRange:
                        {
                            filter = new RemoveDescentRangeSectionsPostProcessFilter(stream, version);
                            break;
                        }
                    default:
                        {
                            Debug.Assert(false);
                            break;
                        }
                }

                Debug.Assert(filter != null);

                m_Filters.Add(filter);
            }

            BuildNamedZones();
        }

#endregion

        private void BuildNamedZones()
        {
            m_NamedZones.Clear();

            foreach (IPostProcessFilter filter in m_Filters)
            {
                m_NamedZones.Add(new PostProcessNamedZone(filter));
            }

            TriggerNamedZonesListChanged();
        }

        private List<object> m_NamedZones = new List<object>();
        private List<IPostProcessFilter> m_Filters = new List<IPostProcessFilter>();
    }
}
